package library.base.mvp.presenter;

import android.os.Bundle;

import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.List;

import library.base.mvp.IContract;
import library.base.mvp.presenter.event.BaseEvent;

import static library.base.GlobalField.PRESENTER_CACHE_TIME;

/**
 * Presenter对应交互业务逻辑，是按照UI的交互逻辑划分的
 *
 * @author Created by qiang.hou on 2018/3/2.
 * @version 1.0
 */
public abstract class BasePresenter implements IContract.IPresenter {

    /**
     * cache event tag
     */
    private List<String> eventTagCache = new ArrayList<>();

    public BasePresenter() {
    }

    public BasePresenter(String eventTag) {
        registerViewEvent(eventTag);
    }

    /**
     * create relationship with view
     *
     * @param eventTag event tag
     */
    public void registerViewEvent(String eventTag) {
        if (!isViewRegistered(eventTag)) {
            validTime = System.currentTimeMillis();
            eventTagCache.add(eventTag);
        }
    }

    /**
     * check if the relationship with view is exist
     *
     * @return boolean
     */
    private boolean isViewRegistered(String eventTag) {
        return eventTagCache.contains(eventTag);
    }

    /**
     * detach the relationship
     */
    public void unRegisterViewEvent(String eventTag) {
        if (isViewRegistered(eventTag)) {
            eventTagCache.remove(eventTag);
        }
        if (eventTagCache.size() == 0) {
            invalidTime = System.currentTimeMillis();
        }
    }

    public void clearViewEvent() {
        eventTagCache.clear();
        invalidTime = System.currentTimeMillis();
    }

    public String getEventTag(int index) {
        return index >= eventTagCache.size() ? null : eventTagCache.get(index);
    }

    /**
     * @param data data
     * @param aTag action tag
     * @param <T>  data type
     */
    public <T> void postEvent(T data, final String aTag) {
        for (String eventTag : eventTagCache) {
            final String viewTag = eventTag;
            EventBus.getDefault().post(new BaseEvent<T, T, T>(data) {
                @Override
                protected String returnThreadTag() {
                    return viewTag;
                }

                @Override
                protected String returnActionTag() {
                    return aTag;
                }
            });
        }
    }

    /**
     * @param data data
     * @param aTag action tag
     * @param <T>  data type
     */
    public <T> void postStickyEvent(T data, final String aTag) {
        for (String eventTag : eventTagCache) {
            final String viewTag = eventTag;
            EventBus.getDefault().postSticky(new BaseEvent<T, T, T>(data) {
                @Override
                protected String returnThreadTag() {
                    return viewTag;
                }

                @Override
                protected String returnActionTag() {
                    return aTag;
                }
            });
        }
    }

    /**
     * @param data data
     * @param aTag action tag
     * @param <T>  data type
     * @param <T2> data type
     */
    public <T, T2> void postEvent(T data, T2 data2, final String aTag) {
        for (String eventTag : eventTagCache) {
            final String viewTag = eventTag;
            EventBus.getDefault().post(new BaseEvent<T, T2, T>(data, data2) {
                @Override
                protected String returnThreadTag() {
                    return viewTag;
                }

                @Override
                protected String returnActionTag() {
                    return aTag;
                }
            });
        }
    }

    /**
     * @param data data
     * @param aTag action tag
     * @param <T>  data type
     * @param <T2> data type
     */
    public <T, T2> void postStickyEvent(T data, T2 data2, final String aTag) {
        for (String eventTag : eventTagCache) {
            final String viewTag = eventTag;
            EventBus.getDefault().postSticky(new BaseEvent<T, T2, T>(data, data2) {
                @Override
                protected String returnThreadTag() {
                    return viewTag;
                }

                @Override
                protected String returnActionTag() {
                    return aTag;
                }
            });
        }
    }

    /**
     * @param data data
     * @param aTag action tag
     * @param <T>  data type
     * @param <T2> data type
     * @param <T3> data type
     */
    public <T, T2, T3> void postEvent(T data, T2 data2, T3 data3, final String aTag) {
        for (String eventTag : eventTagCache) {
            final String viewTag = eventTag;
            EventBus.getDefault().post(new BaseEvent<T, T2, T3>(data, data2, data3) {
                @Override
                protected String returnThreadTag() {
                    return viewTag;
                }

                @Override
                protected String returnActionTag() {
                    return aTag;
                }
            });
        }
    }

    /**
     * @param data data
     * @param aTag action tag
     * @param <T>  data type
     * @param <T2> data type
     * @param <T3> data type
     */
    public <E extends BaseEvent, T, T2, T3> void postStickyEvent(T data, T2 data2, T3 data3, final String aTag) {
        for (String eventTag : eventTagCache) {
            final String viewTag = eventTag;
            EventBus.getDefault().postSticky(new BaseEvent<T, T2, T3>(data, data2, data3) {
                @Override
                protected String returnThreadTag() {
                    return viewTag;
                }

                @Override
                protected String returnActionTag() {
                    return aTag;
                }
            });
        }
    }

    /**
     * @param aTag action tag
     */
    public void postEvent(final String aTag) {
        for (String eventTag : eventTagCache) {
            final String viewTag = eventTag;
            EventBus.getDefault().post(new BaseEvent() {
                @Override
                protected String returnThreadTag() {
                    return viewTag;
                }

                @Override
                protected String returnActionTag() {
                    return aTag;
                }
            });
        }
    }

    /**
     * @param aTag action tag
     * @param <E>  E extends BaseEvent
     */
    public <E extends BaseEvent> void postStickyEvent(final String aTag) {
        for (String eventTag : eventTagCache) {
            final String viewTag = eventTag;
            EventBus.getDefault().postSticky(new BaseEvent() {
                @Override
                protected String returnThreadTag() {
                    return viewTag;
                }

                @Override
                protected String returnActionTag() {
                    return aTag;
                }
            });
        }
    }

    /**
     * @param event E extends BaseEvent
     */
    public <E extends BaseEvent> void postEvent(E event) {
        EventBus.getDefault().post(event);
    }

    /**
     * @param event E extends BaseEvent
     */
    public <E extends BaseEvent> void postStickyEvent(E event) {
        EventBus.getDefault().postSticky(event);
    }

    /**
     * time for registering new event tag of view
     */
    private long validTime = 0;
    /**
     * time for clear new event tag of view
     */
    private long invalidTime = 0;

    public boolean isEffective() {
        return (invalidTime - validTime) / 1000 < PRESENTER_CACHE_TIME;
    }

    @Override
    public void onCreate() {
    }

    @Override
    public void onStart() {
    }

    @Override
    public void onResume() {
    }

    @Override
    public void onPause() {
    }

    @Override
    public void onStop() {
    }

    @Override
    public void onDestroy() {
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
    }
}
